#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
彩票规则模块
定义各种彩票的规则和中奖计算方法
"""

import json
import os
from datetime import datetime

class LotteryRule:
    """
    彩票规则基类
    """
    def __init__(self, name):
        self.name = name
    
    def calculate_winning_level(self, user_numbers, winning_numbers):
        """
        计算中奖等级
        """
        raise NotImplementedError("子类必须实现此方法")
    
    def get_prize_info(self, level):
        """
        获取奖项信息
        """
        raise NotImplementedError("子类必须实现此方法")
    
    # 添加保存开奖号码的方法
    def save_winning_numbers(self, winning_numbers, issue=None):
        """
        保存开奖号码到文件
        """
        # 修改数据目录路径，使其适应打包后的环境
        data_dir = os.path.expanduser("~/.local/share/gambling-memories/data")
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)
            
        filename = f"{data_dir}/{self.name}_winning_numbers.json"
        
        # 读取现有数据
        if os.path.exists(filename):
            with open(filename, 'r', encoding='utf-8') as f:
                try:
                    data = json.load(f)
                except json.JSONDecodeError:
                    data = []
        else:
            data = []
        
        # 创建新记录
        record = {
            "issue": issue if issue else datetime.now().strftime("%Y%m%d%H%M%S"),
            "winning_numbers": winning_numbers,
            "timestamp": datetime.now().isoformat()
        }
        
        # 添加到数据中
        data.append(record)
        
        # 保存到文件
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        
        return True

    # 添加保存用户号码的方法
    def save_user_numbers(self, user_numbers, issue=None):
        """
        保存用户号码到文件
        """
        # 修改数据目录路径，使其适应打包后的环境
        data_dir = os.path.expanduser("~/.local/share/gambling-memories/data")
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)
            
        filename = f"{data_dir}/{self.name}_user_numbers.json"
        
        # 读取现有数据
        if os.path.exists(filename):
            with open(filename, 'r', encoding='utf-8') as f:
                try:
                    data = json.load(f)
                except json.JSONDecodeError:
                    data = []
        else:
            data = []
        
        # 创建新记录
        record = {
            "issue": issue if issue else datetime.now().strftime("%Y%m%d%H%M%S"),
            "user_numbers": user_numbers,
            "timestamp": datetime.now().isoformat()
        }
        
        # 添加到数据中
        data.append(record)
        
        # 保存到文件
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        
        return True

    # 添加对比开奖号码和用户号码的功能
    def compare_numbers(self, user_numbers, winning_numbers):
        """
        对比用户号码和开奖号码，返回中奖详情
        """
        raise NotImplementedError("子类必须实现此方法")

class DoubleColorBallRule(LotteryRule):
    """
    双色球规则
    红球6个(1-33)，蓝球1个(1-16)
    """
    def __init__(self):
        super().__init__("double_color_ball")
    
    def calculate_winning_level(self, user_numbers, winning_numbers):
        """
        计算双色球中奖等级
        user_numbers: [[红球号码列表], 蓝球号码]
        winning_numbers: [[红球号码列表], 蓝球号码]
        """
        user_red, user_blue = user_numbers
        winning_red, winning_blue = winning_numbers
        
        # 计算红球匹配数量
        red_matches = len(set(user_red) & set(winning_red))
        
        # 检查蓝球是否匹配
        blue_match = (user_blue == winning_blue)
        
        # 根据规则判断中奖等级
        if red_matches == 6 and blue_match:
            return 1  # 一等奖
        elif red_matches == 6 and not blue_match:
            return 2  # 二等奖
        elif red_matches == 5 and blue_match:
            return 3  # 三等奖
        elif (red_matches == 5 and not blue_match) or (red_matches == 4 and blue_match):
            return 4  # 四等奖
        elif (red_matches == 4 and not blue_match) or (red_matches == 3 and blue_match):
            return 5  # 五等奖
        elif blue_match:
            return 6  # 六等奖
        else:
            return 0  # 未中奖
    
    def get_prize_info(self, level):
        """
        获取奖项信息
        """
        prize_info = {
            1: {"name": "一等奖", "desc": "6个红球+1个蓝球"},
            2: {"name": "二等奖", "desc": "6个红球"},
            3: {"name": "三等奖", "desc": "5个红球+1个蓝球"},
            4: {"name": "四等奖", "desc": "5个红球或4个红球+1个蓝球"},
            5: {"name": "五等奖", "desc": "4个红球或3个红球+1个蓝球"},
            6: {"name": "六等奖", "desc": "1个蓝球"},
            0: {"name": "未中奖", "desc": "未达到中奖条件"}
        }
        return prize_info.get(level, {"name": "未知", "desc": "未知奖项"})
    
    # 添加保存开奖号码的特定实现
    def save_winning_numbers(self, winning_numbers, issue=None):
        """
        保存双色球开奖号码
        winning_numbers: [[红球号码列表], 蓝球号码]
        """
        # 验证号码格式
        red_balls, blue_ball = winning_numbers
        if len(red_balls) != 6 or not (1 <= blue_ball <= 16):
            raise ValueError("双色球号码格式不正确")
        
        # 调用父类方法保存
        return super().save_winning_numbers(winning_numbers, issue)

    # 添加保存用户号码的特定实现
    def save_user_numbers(self, user_numbers, issue=None):
        """
        保存双色球用户号码
        user_numbers: [[红球号码列表], 蓝球号码]
        """
        # 验证号码格式
        red_balls, blue_ball = user_numbers
        if len(red_balls) != 6 or not (1 <= blue_ball <= 16):
            raise ValueError("双色球号码格式不正确")
        
        # 调用父类方法保存
        return super().save_user_numbers(user_numbers, issue)

    # 实现双色球号码对比功能
    def compare_numbers(self, user_numbers, winning_numbers):
        """
        对比双色球用户号码和开奖号码，返回中奖详情
        user_numbers: [[红球号码列表], 蓝球号码]
        winning_numbers: [[红球号码列表], 蓝球号码]
        返回: {
            "red_matches": 匹配的红球号码列表,
            "blue_match": 蓝球是否匹配,
            "level": 中奖等级,
            "prize_info": 奖项信息
        }
        """
        user_red, user_blue = user_numbers
        winning_red, winning_blue = winning_numbers
        
        # 计算红球匹配
        red_matches = list(set(user_red) & set(winning_red))
        
        # 检查蓝球是否匹配
        blue_match = (user_blue == winning_blue)
        
        # 计算中奖等级
        level = self.calculate_winning_level(user_numbers, winning_numbers)
        prize_info = self.get_prize_info(level)
        
        return {
            "red_matches": red_matches,
            "blue_match": blue_match,
            "level": level,
            "prize_info": prize_info
        }

class SuperLottoRule(LotteryRule):
    """
    大乐透规则
    前区5个(1-35)，后区2个(1-12)
    """
    def __init__(self):
        super().__init__("super_lotto")
    
    def calculate_winning_level(self, user_numbers, winning_numbers):
        """
        计算大乐透中奖等级
        user_numbers: [[前区号码列表], [后区号码列表]]
        winning_numbers: [[前区号码列表], [后区号码列表]]
        """
        user_front, user_back = user_numbers
        winning_front, winning_back = winning_numbers
        
        # 计算前区和后区匹配数量
        front_matches = len(set(user_front) & set(winning_front))
        back_matches = len(set(user_back) & set(winning_back))
        
        # 根据规则判断中奖等级
        if front_matches == 5 and back_matches == 2:
            return 1  # 一等奖
        elif front_matches == 5 and back_matches == 1:
            return 2  # 二等奖
        elif front_matches == 5 and back_matches == 0:
            return 3  # 三等奖
        elif front_matches == 4 and back_matches == 2:
            return 4  # 四等奖
        elif (front_matches == 4 and back_matches == 1) or (front_matches == 3 and back_matches == 2):
            return 5  # 五等奖
        elif (front_matches == 4 and back_matches == 0) or (front_matches == 3 and back_matches == 1) or (front_matches == 2 and back_matches == 2) or (front_matches == 1 and back_matches == 2) or (front_matches == 0 and back_matches == 2):
            return 6  # 六等奖
        else:
            return 0  # 未中奖
    
    def get_prize_info(self, level):
        """
        获取奖项信息
        """
        prize_info = {
            1: {"name": "一等奖", "desc": "5个前区号码+2个后区号码"},
            2: {"name": "二等奖", "desc": "5个前区号码+1个后区号码"},
            3: {"name": "三等奖", "desc": "5个前区号码"},
            4: {"name": "四等奖", "desc": "4个前区号码+2个后区号码"},
            5: {"name": "五等奖", "desc": "4个前区号码+1个后区号码或3个前区号码+2个后区号码"},
            6: {"name": "六等奖", "desc": "4个前区号码或3个前区号码+1个后区号码或2个前区号码+2个后区号码或1个前区号码+2个后区号码或2个后区号码"},
            0: {"name": "未中奖", "desc": "未达到中奖条件"}
        }
        return prize_info.get(level, {"name": "未知", "desc": "未知奖项"})
    
    # 添加保存开奖号码的特定实现
    def save_winning_numbers(self, winning_numbers, issue=None):
        """
        保存大乐透开奖号码
        winning_numbers: [[前区号码列表], [后区号码列表]]
        """
        # 验证号码格式
        front_balls, back_balls = winning_numbers
        if len(front_balls) != 5 or len(back_balls) != 2 or not (1 <= min(back_balls) <= max(back_balls) <= 12):
            raise ValueError("大乐透号码格式不正确")
        
        # 调用父类方法保存
        return super().save_winning_numbers(winning_numbers, issue)

    # 添加保存用户号码的特定实现
    def save_user_numbers(self, user_numbers, issue=None):
        """
        保存大乐透用户号码
        user_numbers: [[前区号码列表], [后区号码列表]]
        """
        # 验证号码格式
        front_balls, back_balls = user_numbers
        if len(front_balls) != 5 or len(back_balls) != 2 or not (1 <= min(back_balls) <= max(back_balls) <= 12):
            raise ValueError("大乐透号码格式不正确")
        
        # 调用父类方法保存
        return super().save_user_numbers(user_numbers, issue)

    # 实现大乐透号码对比功能
    def compare_numbers(self, user_numbers, winning_numbers):
        """
        对比大乐透用户号码和开奖号码，返回中奖详情
        user_numbers: [[前区号码列表], [后区号码列表]]
        winning_numbers: [[前区号码列表], [后区号码列表]]
        返回: {
            "front_matches": 匹配的前区号码列表,
            "back_matches": 匹配的后区号码列表,
            "level": 中奖等级,
            "prize_info": 奖项信息
        }
        """
        user_front, user_back = user_numbers
        winning_front, winning_back = winning_numbers
        
        # 计算前区和后区匹配
        front_matches = list(set(user_front) & set(winning_front))
        back_matches = list(set(user_back) & set(winning_back))
        
        # 计算中奖等级
        level = self.calculate_winning_level(user_numbers, winning_numbers)
        prize_info = self.get_prize_info(level)
        
        return {
            "front_matches": front_matches,
            "back_matches": back_matches,
            "level": level,
            "prize_info": prize_info
        }

# 彩票规则注册表
LOTTERY_RULES = {
    "double_color_ball": DoubleColorBallRule(),
    "super_lotto": SuperLottoRule()
}

def get_lottery_rule(lottery_type):
    """
    获取彩票规则对象
    """
    return LOTTERY_RULES.get(lottery_type)

# 添加通用的保存按钮处理函数
def handle_save_button(lottery_type, winning_numbers, issue=None):
    """
    处理保存按钮点击事件
    """
    try:
        rule = get_lottery_rule(lottery_type)
        if rule:
            return rule.save_winning_numbers(winning_numbers, issue)
        else:
            raise ValueError(f"未知的彩票类型: {lottery_type}")
    except Exception as e:
        print(f"保存开奖号码失败: {e}")
        return False

# 添加通用的保存用户号码处理函数
def handle_save_user_numbers(lottery_type, user_numbers, issue=None):
    """
    处理保存用户号码按钮点击事件
    """
    try:
        rule = get_lottery_rule(lottery_type)
        if rule:
            return rule.save_user_numbers(user_numbers, issue)
        else:
            raise ValueError(f"未知的彩票类型: {lottery_type}")
    except Exception as e:
        print(f"保存用户号码失败: {e}")
        return False

# 添加通用的号码对比函数
def handle_compare_numbers(lottery_type, user_numbers, winning_numbers):
    """
    处理号码对比
    """
    try:
        rule = get_lottery_rule(lottery_type)
        if rule:
            return rule.compare_numbers(user_numbers, winning_numbers)
        else:
            raise ValueError(f"未知的彩票类型: {lottery_type}")
    except Exception as e:
        print(f"号码对比失败: {e}")
        return None

# 使用示例和测试代码
if __name__ == "__main__":
    # 测试双色球规则
    dcb_rule = get_lottery_rule("double_color_ball")
    user_numbers = [[1, 2, 3, 4, 5, 6], 7]
    winning_numbers = [[1, 2, 3, 4, 5, 6], 7]
    level = dcb_rule.calculate_winning_level(user_numbers, winning_numbers)
    prize = dcb_rule.get_prize_info(level)
    print(f"双色球中奖等级: {level}, 奖项: {prize}")
    
    # 测试大乐透规则
    sl_rule = get_lottery_rule("super_lotto")
    user_numbers = [[1, 2, 3, 4, 5], [1, 2]]
    winning_numbers = [[1, 2, 3, 4, 5], [1, 2]]
    level = sl_rule.calculate_winning_level(user_numbers, winning_numbers)
    prize = sl_rule.get_prize_info(level)
    print(f"大乐透中奖等级: {level}, 奖项: {prize}")